Description:
A field is accessed in at least one place within a synchronized section (with locked monitors), and in one or more other places, it is accessed without locking any monitor or with locking a different monitor.
RC analyzes all thread entry points in the program. By default, entry points are determined as
methods passed to the constructor of delegate
System.Threading.ThreadStart.
However, it is possible to treat any public method as an entry point (it is useful for library functions
that can be invoked in any context). Then the resource analyzer
recursively builds resource lock closure, by traversing all method invocation from entry points and
keeping track of locked resources. As a result of such analysis, we detect fields
that can be concurrently accessed by different threads (it is assumed that all code reachable from the entry
points is reentrant) and know the set of locked monitors protecting such access.
If access to the same field is performed with an inconsistent set of locked monitors, then
the Race Condition message is produced. Inconsistent, in this context, means that at least one set is not empty and
an intersection of all sets is empty. If a field is accessed without any locked monitor, then
the Field is accessed concurrently without locking message is produced,
otherwise the Field is accessed concurrently with different lock sets message is produced. To
minimize the number of false race conditions detected, this audit considers only update access to the fields,
so if a field is not modified, a message will not be produced.
Incorrect:
class Account {
private long amount;
public void Deposit(int sum) {
lock (this) {
amount += sum;
}
}
public void AccumulatePersents(float percent) {
amount += (long)(amount * percent); // here 'amount' is accessed without lock
}
}
Correct:
class Account {
private long amount;
public void Deposit(int sum) {
lock (this) {
amount += sum;
}
}
public void AccumulatePersents(float percent) {
lock (this) {
amount += (long)(amount * percent);
}
}
}